<script lang="ts" setup>
import { onMounted, onUnmounted, ref, reactive, nextTick, PropType } from "vue";
import { ElScrollbar } from "element-plus";
import type { FormRules, FormInstance } from "element-plus";

const emits = defineEmits(["update:modelValue", "change"]);
const props = defineProps({
  modelValue: {
    type: Object as PropType<{
      relation: "or" | "and";
      fields: { field: string; oper: string; value?: any }[];
    }>,
    default: () => {
      return {
        relation: "and",
        fields: [],
      };
    },
  },
  fields: {
    type: Array as PropType<
      {
        label: string;
        prop: string;
        type?: string;
        [key: string]: any;
      }[]
    >,
    default: () => {
      return [];
    },
  },
});

const formRef = ref<FormInstance>();
const buttonRef = ref();
const innerRef = ref<HTMLDivElement>();
const scrollbarRef = ref<InstanceType<typeof ElScrollbar>>();
const visible = ref(false);
const max = ref(0);

const allOpers = [
  {
    label: "等于",
    value: "eq",
  },
  {
    label: "不等于",
    value: "ne",
  },
  {
    label: "大于",
    value: "gt",
  },
  {
    label: "小于",
    value: "lt",
  },
  {
    label: "大于等于",
    value: "gte",
  },
  {
    label: "小于等于",
    value: "lte",
  },
  {
    label: "包含",
    value: "like",
  },
  {
    label: "不包含",
    value: "noLike",
  },
  {
    label: "为空",
    value: "isNull",
  },
  {
    label: "不为空",
    value: "isNotNull",
  },
]

const fildOpers: {
  [key: string]: string[];
} = {
  datetime: ['eq', 'gt', 'lt', 'isNull', 'isNotNull'],
  date: ['eq', 'gt', 'lt', 'isNull', 'isNotNull'],
  number: ['eq', 'gt', 'lt', 'isNull', 'isNotNull'],
}

//引入自定义验证规则
const formRules = reactive<FormRules>({});

const searchFilterData = ref<{
  relation: "and" | "or";
  fields: {
    field: string;
    oper: string;
    value?: any;
  }[];
}>({
  relation: "and",
  fields: [],
});

const clearSearchFilterItem = () => {
  searchFilterData.value.fields = [];
};

const addSearchFilterItem = async () => {
  const formEl = formRef.value;
  if (!formEl) return;

  await formEl.validate((valid, fields) => {
    if (valid) {
      searchFilterData.value.fields.push({
        field: "",
        oper: "",
        value: undefined
      });
      // 使用
      nextTick(() => {
        scrollbarRef.value!.setScrollTop(innerRef.value!.clientHeight);
      });
    } else {
      console.log("error submit!", fields);
    }
  });
};

const removeSearchFilterItem = (index: number) => {
  searchFilterData.value.fields.splice(index, 1);
};

const handelVisible = async () => {
  if (visible.value) {
    const formEl = formRef.value;
    if (!formEl) return;

    await formEl.validate((valid, fields) => {
      if (valid) {
        visible.value = false;
      } else {
        console.log("error submit!", fields);
        ElMessage({
          message: `请设置合法的过滤条件`,
          type: "warning",
          grouping: true,
        });
      }
    });
  }
};

const getSearchFilterItem = () => {
  // 修改 modelValue 属性
  emits("update:modelValue", searchFilterData.value);
  // 选择类需要的事件
  emits("change", searchFilterData.value);
};

const getOperOptions: (field: string) => {
  label: string;
  value: string;
}[] = (field) => {
  if (!field) {
    return [];
  }
  const item = props.fields.find(
    (item: { prop: string }) => item.prop === field,
  );
  if (item && item.type && fildOpers[item.type] && fildOpers[item.type].length) {
    return allOpers.filter(o => item.type && fildOpers[item.type].includes(o.value));
  } else {
    return allOpers;
  }
};

const getFieldConfig: (field: string) => {
  label: string;
  value: string;
  type?: string;
  [key: string]: any;
} = (field) => {
  if (!field) {
    return {};
  }
  const item: any = props.fields.find(
    (item: { prop: string }) => item.prop === field,
  );
  return item || {}
};

onMounted(() => {
  document.getElementById("app")?.addEventListener("click", handelVisible);
  if (innerRef.value) {
    max.value = innerRef.value!.clientHeight - 380;
  }
});

//vue3 使用生命周期销毁钩子
onUnmounted(() => {
  // 移除监听事件
  document.getElementById("app")?.removeEventListener("click", handelVisible);
});
</script>

<template>
  <el-tooltip class="box-item" effect="dark" content="设置筛选条件" placement="top">
    <el-button class="search-filter-btn" ref="buttonRef" type="primary" @click.stop="visible = true" plain>
      <el-badge is-dot :value="searchFilterData.fields.length" :hidden="!searchFilterData.fields.length">
        <el-icon>
          <Filter />
        </el-icon>
      </el-badge>
    </el-button>
  </el-tooltip>
  <el-popover :visible="visible" placement="bottom-end" :width="560" trigger="click" @hide="getSearchFilterItem"
    :virtual-ref="buttonRef" virtual-triggering>
    <div @click.prevent="($event) => $event.stopPropagation()">
      <el-form :rules="formRules" ref="formRef" :model="searchFilterData" label-width="0">
        <div class="pb-2">
          <div class="flex justify-between items-center">
            <div>
              <span>设置筛选条件</span>
            </div>
            <div>
              <el-form-item labelWidth="0" prop="relation" style="margin: 0">
                <!--								<el-switch-->
                <!--									v-model="searchFilterData.relation"-->
                <!--									inline-prompt-->
                <!--									style="&#45;&#45;el-switch-on-color: #13ce66; &#45;&#45;el-switch-off-color: #ff4949"-->
                <!--									active-text="所有条件"-->
                <!--									inactive-text="任一条件"-->
                <!--								/>-->
                <!-- <el-radio-group v-model="searchFilterData.relation">
										<el-radio value="and">所有条件</el-radio>
										<el-radio value="or">任一条件</el-radio>
									</el-radio-group> -->
                <el-select v-model="searchFilterData.relation" placeholder="请选择" style="width: 140px"
                  :popperAppendToBody="false" size="small">
                  <el-option label="符合以下所有条件" value="and" />
                  <el-option label="符合以下任一条件" value="or" />
                </el-select>
              </el-form-item>
            </div>
          </div>
        </div>
        <div style="max-height: 220px; margin-right: -12px" v-if="searchFilterData.fields.length">
          <el-scrollbar ref="scrollbarRef" :height="searchFilterData.fields.length > 5 ? '220px' : 'auto'" always>
            <div style="padding-right: 12px" ref="innerRef">
              <div class="flex pb-2" v-for="(i, index) in searchFilterData.fields" :key="index">
                <div class="flex-1">
                  <el-row :gutter="10">
                    <el-col :span="8">
                      <el-form-item :prop="['fields', index.toString(), 'field']" style="margin: 0" required
                        inline-message :show-message="false">
                        <el-select v-model="i['field']" placeholder="请选择" :popperAppendToBody="false">
                          <el-option v-for="o in fields" :key="o.prop" :label="o.label" :value="o.prop" />
                        </el-select>
                      </el-form-item>
                    </el-col>
                    <el-col :span="8">
                      <el-form-item :prop="['fields', index.toString(), 'oper']" style="margin: 0" required
                        inline-message :show-message="false">
                        <el-select v-model="i['oper']" placeholder="请选择" :popperAppendToBody="false">
                          <el-option v-for="o in getOperOptions(i.field)" :key="o.value" :label="o.label"
                            :value="o.value" />
                        </el-select>
                      </el-form-item>
                    </el-col>
                    <el-col :span="8">
                      <template v-if="
                        i['oper'] !== 'isNull' && i['oper'] !== 'isNotNull'
                      ">
                        <el-form-item :prop="['fields', index.toString(), 'value']" style="margin: 0" required
                          inline-message :show-message="false">

                          <el-date-picker style="width: 100%;" type="datetime"
                            v-if="getFieldConfig(i.field).type === 'datetime'" v-model="i['value']" placeholder="请输入" />

                          <el-input-number style="width: 100%;" v-else-if="getFieldConfig(i.field).type === 'number'"
                            v-model="i['value']" :min="getFieldConfig(i.field).min" :max="getFieldConfig(i.field).min"
                            controls-position="right" />

                          <el-input style="width: 100%;" v-else v-model="i['value']" placeholder="请输入" />
                        </el-form-item>
                      </template>
                    </el-col>
                  </el-row>
                </div>
                <div style="width: 24px; margin-left: 10px">
                  <el-button text icon="Close" circle @click="removeSearchFilterItem(index)" />
                </div>
              </div>
            </div>
          </el-scrollbar>
        </div>
        <div class="flex justify-center" v-else>
          <el-empty description="点击下方按钮添加过滤条件" :image-size="80" />
        </div>
        <div class="flex pt-2">
          <el-button type="primary" @click="addSearchFilterItem" size="small">添加条件</el-button>
          <el-button v-if="searchFilterData.fields.length" link @click="clearSearchFilterItem" size="small">清空条件
          </el-button>
        </div>
      </el-form>
    </div>
  </el-popover>
</template>
